package com.lz.frame.filter.filter;

import java.util.*;
import java.util.concurrent.atomic.*;
import com.google.gson.Gson;
import com.lz.frame.config.security.MyUserDetails02;
import com.lz.frame.config.security.SecurityConfig;
import com.lz.frame.domain.VO.UserVO;
import com.lz.frame.domain.entity.User;
import com.lz.frame.filter.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
@Slf4j
public class ZzOncePerRequestFilter extends OncePerRequestFilter {

    //我要把这个类出现的魔法值写在这
    private static final String TOKEN = "TOKEN";
    //dev
    private static final String DEV = "dev";
    //  虚拟身份名称
    private static final String ANONYMOUS_IDENTITY = "virtualIdentity";
    //虚拟ID
    private static final String ANONYMOUS_ID = "1113";


    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private Gson gson;

    @Resource
    private SecurityConfig securityConfig;
    @Resource
    private JwtUtil jwtUtil;

    /**
     * 查看接口是否为匿名访问接口
     * 从请求头里面获取Token
     * 向cookie中设置token
     * 向SecurityContext中设置用户信息
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (securityConfig.getAnonymousAccessUrls().contains(request.getRequestURI())) {
            //如果是匿名接口路径，则放行
            log.info("获取TOKEN-----AnonymousAccessUrls");
            //放行前向SecurityContext设置用户信息
            UserVO userVO = new UserVO();
            User user = new User();
            userVO.setUser(user);
            MyUserDetails02 myUserDetails = new MyUserDetails02(userVO);
            UsernamePasswordAuthenticationToken UserDetailsAuthenticationToken = new UsernamePasswordAuthenticationToken(myUserDetails, null, myUserDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(UserDetailsAuthenticationToken);
            filterChain.doFilter(request, response);
            return;
        }
        AtomicReference<String> token = new AtomicReference<>();


        token.set(request.getHeader(TOKEN));
        if (token.get() != null && !token.get().trim().isEmpty()) {
            log.info("获取TOKEN-----HEADER=>{}", token.get());
            Cookie cookie = new Cookie(TOKEN, token.get());
            cookie.setMaxAge(60 * 60 * 24 * 7);
            response.addCookie(cookie);
            read(token.get(), request, response, filterChain);

            return;
        }

        //查看cookie是否存在
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            long count = Arrays.stream(cookies).filter(cookie -> {
                if (cookie.getName().equals(TOKEN)) {
                    token.set(cookie.getValue());
                    return true;
                }
                return false;
                //todo 未确定token的有效性
            }).count();
            if (count > 0) {
                log.info("获取TOKEN-----COOKIE=>{}", token.get());
                read(token.get(), request, response, filterChain);
                return;
            }
        }




        filterChain.doFilter(request, response);
    }

    public void read(String token, HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {

        MyUserDetails02 myUserDetails = jwtUtil.parseToUser(token);
        UsernamePasswordAuthenticationToken UserDetailsAuthenticationToken = new UsernamePasswordAuthenticationToken(myUserDetails, null, myUserDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(UserDetailsAuthenticationToken);
        try {
            filterChain.doFilter(request, response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ServletException e) {
            throw new RuntimeException(e);
        }
    }

}
